#include "bisection.h"

#include <cassert>
#include <cmath>

namespace NumericalAnalysis
{
       // Performs the bisection method.
    // It takes a BisectionInputData and returns a BisectionOutputData structs.
    BisectionOutputData BisectionMethod(const BisectionInputData& inputData)
    {
    	assert(inputData.mFunction && "BisectionMethod: NULL pointer");

    	// Defines an instance of the output data.
    	BisectionOutputData outputdata;

    	// While we do not have to stop iterations, we continue with them.
    	bool continueIterations = true;
    	double currentLeftLimit = inputData.mLeftLimit;
    	double currentRightLimit = inputData.mRightLimit;
    	while(continueIterations)
    	{
    		// Calculate a new approximation.
    		const double currentApproximation = (currentLeftLimit + currentRightLimit) / 2.0;

    		// Store the new approximation inside the output data.
    		outputdata.mApproximations.push_back(currentApproximation);

    		// Check if we finished due stop bound condition.
    		const double valuedCurrentApproximation = inputData.mFunction(currentApproximation);
    		if(abs(valuedCurrentApproximation) < inputData.mStopBound)
    		{
    			// Stop iterations.	
    			continueIterations = false;

    			// Store the last approximation.
    			outputdata.mLastApproximation = currentApproximation;
    			
    			// Store the function valued on the last approximation.
    			outputdata.mValuedLastApproximation = inputData.mFunction(currentApproximation);
    		}

    		// If not we update the interval ends
    		else
    		{
    			// If the last approximation has different sign
    			// than the left limit, then we update the right limit.    			
    			if(inputData.mFunction(currentLeftLimit) * valuedCurrentApproximation < 0.0)
    				currentRightLimit = currentApproximation;

    			// If not, then we update the left limit.
    			else
    				currentLeftLimit = currentApproximation;
    		}
    	}

    	return outputdata;
    }
}
